package com.mitac.mcd.cs.mobiletracking.directoryserver;

import java.beans.PropertyVetoException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.SocketException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.mitac.mcd.cs.mobiletracking.directoryserver.util.BusinessUtil;
import com.mitac.mcd.cs.mobiletracking.directoryserver.util.ClientCMDEnum;
import com.mitac.mcd.cs.mobiletracking.directoryserver.util.DBConnection;
import com.mitac.mcd.cs.mobiletracking.directoryserver.util.Formatter;
import com.mitac.mcd.cs.mobiletracking.directoryserver.util.RandomId;
import com.mitac.mcd.cs.mobiletracking.directoryserver.util.ServerBean;

import net.sf.json.JSONObject;



public class MobileServerThread extends Thread{

	MobileServer server;
    Socket socket;
    public String exceptionPropCode = null;
    int status = 1;//1 means success, 0 means error
    public PrintStream PS = null;
    private Calendar dirStartTime = null;
    private Calendar dirFinishTime = null;
    
    public MobileServerThread(MobileServer server,Socket socket) {
        this.server = server;
        this.socket = socket;
        try {
			PS = new PrintStream(socket.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}
        this.start();
    }
	
    /**
     * get appropriate socket server ip and port
     * @return
     */
    public Map<String,String> getSocketServer(){
    	Map<String,String> map = new HashMap<String,String>();
    	String ip = null;String port = null;
    	//how to get most appropriate socket server
    	List<ServerBean> list = new ArrayList<ServerBean>();
    	java.sql.Connection dbc = null;
        PreparedStatement pst = null;
        String sqlA = " SELECT SC.SERVER_ID,SC.SERVER_PUBLIC_IPADDRESS,SC.SERVER_PUBLIC_PORT,SC.SERVER_WEIGHT,SC.SERVER_MAXCOUNT,OC.ONLINE_COUNT "+
        				" FROM SERVERS_CONFIGURATION SC LEFT JOIN "+
        				" (SELECT SERVER_ID,COUNT(UUID) ONLINE_COUNT FROM ONLINE_CLIENT GROUP BY SERVER_ID ) OC "+
        				" ON SC.SERVER_ID = OC.SERVER_ID " +
        				" WHERE SC.SERVER_TYPE = 1  ";
        BusinessUtil.aLogger.info("sql=="+sqlA);
        ResultSet rs = null;
        try {
        	dbc = DBConnection.getConnection("gpsdata");
			pst = dbc.prepareStatement(sqlA);
			rs = pst.executeQuery();
			while(rs.next()){
				ServerBean sb = new ServerBean();
				sb.serverId = rs.getInt("SERVER_ID");
				sb.publicIp = rs.getString("SERVER_PUBLIC_IPADDRESS");
				sb.publicPort = rs.getInt("SERVER_PUBLIC_PORT");
				sb.weight = rs.getDouble("SERVER_WEIGHT");
				sb.maxCount = rs.getInt("SERVER_MAXCOUNT");
				sb.onlineCount = rs.getInt("ONLINE_COUNT");
				sb.grade = (sb.maxCount-sb.onlineCount)*sb.weight;
				list.add(sb);
			}
			ServerBean t_bean = null;double t_grade = 0;
			for(ServerBean bean:list){
				if(t_grade<bean.grade){
					t_grade = bean.grade;
					t_bean = bean;
				}
			}
			ip = t_bean.publicIp;port = String.valueOf(t_bean.publicPort);
		} catch (SQLException e) {
			BusinessUtil.sLogger.error("getSocketServer() 发生异常:"+e);
		} catch (PropertyVetoException e) {
			BusinessUtil.sLogger.error("getSocketServer() 发生异常:"+e);
		}
		try
        {
			if(null!=rs) rs.close();
            dbc.close();
            pst.close();
        }catch(SQLException e)
        {
            e.printStackTrace();
        }
        
    	map.put("ip", ip);
    	map.put("port", port);
    	return map;
    }
    
    public void run() {
    	String time = Formatter.r_sdf.format(new Date());
    	String ID = time+"_"+RandomId.getRandomString(6);
    	BusinessUtil.aLogger.info("新开一个线程:"+socket+" ID:"+ID);
        BufferedReader inBr = null;
        String str = null;
        InputStream Is = null;
        try {
        	boolean flowFlag = true;
        	Is = socket.getInputStream();
            inBr = new BufferedReader(new InputStreamReader(Is,MobileServer.ENCODING));
            str = inBr.readLine();
            BusinessUtil.aLogger.info("接收到的讯息为:"+str);
            JSONObject jsonObject = null;
            if(str!=null&&!"".equals(str)){
            	try{
            		jsonObject = JSONObject.fromObject(str);
            	}catch(Exception e1){//上传数据格式不是规范的json格式
            		e1.printStackTrace();
            		//log to db
            		exceptionPropCode = "E008";
            		status = 0;
        			BusinessUtil.sendMessage("aut","","",status,exceptionPropCode,PS);
        			flowFlag = false;
            	}
            	if(flowFlag){//validate successfully then continue
            		//request为验证
                    if (BusinessUtil.judge(jsonObject).equals(ClientCMDEnum.CMD.socketsvrreq)){
                    	BusinessUtil.aLogger.info("Request Type==="+ClientCMDEnum.CMD.socketsvrreq);
                    	//set aut start time
                    	dirStartTime = Calendar.getInstance();
                        Map<String,String> map = getSocketServer();
                        //set aut finish time
                        dirFinishTime = Calendar.getInstance();
                        String ip = map.get("ip").toString();
                        String port = map.get("port").toString();
                        //begin return json object
                        BusinessUtil.sendMessage("socketsvrreq",ip,port,status,exceptionPropCode,PS);
                        //end return json object
                    }else if (BusinessUtil.judge(jsonObject).equals(ClientCMDEnum.CMD.notgood)){
                    	//begin return json object
                    	exceptionPropCode = "E009";
                		status = 0;
                        BusinessUtil.sendMessage("socketsvrreq",status,exceptionPropCode,PS);
                        //end return json object
                    }
            	}
            }
	        
        }catch (SocketException ex) {
            BusinessUtil.aLogger.info(" ERROR:"+ex);
        }catch(IOException e){
            BusinessUtil.aLogger.info(" ERROR:"+e);
        }finally{
            try {
                if (!socket.isClosed()) socket.close();
                Is.close();
                inBr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            BusinessUtil.aLogger.info(ID+" 线程已经结束.....");
        }
    }
}
